﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Net;
using System.Net.Mail;
using CHGK.web.UI;
using CHGK.web.UI.Models;
using CHGK.web.UI.Core;
using ChGK.Data;

namespace CHGK.web.UI.Controllers
{
    public class HomeController : Controller, IDisposable
    {
        private DataManager _DataManager;
        
        public HomeController()
        {
            _DataManager = new DataManager();
        }

        private int NumberOfCheckedQuestions(Tour Tour, int NumberOfControlTeams)
        {
            int _TeamID, k;
            int QuestionNumber;
            for (QuestionNumber = 1; QuestionNumber <= Tour.NumberOfQuestions; QuestionNumber++)
            {
                k = 0;
                for (int i = 1; i <= NumberOfControlTeams; i++)
                {
                    if (_DataManager.Teams.GetTeam(Tour.CompetitionID, i) == null)
                    {
                        return 0;
                    }
                    else
                    {
                        _TeamID = _DataManager.Teams.GetTeam(Tour.CompetitionID, i).ID;
                    }

                    if (_DataManager.Answers.GetAnswer(_TeamID, Tour.ID, QuestionNumber) != null && _DataManager.Answers.GetAnswer(_TeamID, Tour.ID, QuestionNumber).IsCorrect != null)
                    {
                        break;
                    }
                    k++;
                }
                if (k == NumberOfControlTeams)
                {
                    return QuestionNumber - 1;
                }
            }
            return QuestionNumber - 1;
        }

        private void sorting(ref short[][] arr, int first, int last, int LastElem)
        {
            short[] p = arr[(last - first) / 2 + first];
            short[] temp;
            int i = first, j = last;
            while (i <= j)
            {
                while (arr[i][LastElem] > p[LastElem] && i <= last) ++i;
                while (arr[j][LastElem] < p[LastElem] && j >= first) --j;
                if (i <= j)
                {
                    temp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = temp;
                    ++i; --j;
                }
            }
            if (j > first) sorting(ref arr, first, j, LastElem);
            if (i < last) sorting(ref arr, i, last, LastElem);
        }

        private void QuickSort(ref short[][] array, int n, int last)
        {

            sorting(ref array, 0, n - 1, last);

        }

        private void InitialazeTable(ref short[][] Table, IEnumerable<Team> Teams, int end)
        {
            int i = 0;

            foreach (Team t in Teams)
            {
                Table[i] = new short[end + 2];
                Table[i][0] = t.Number;
                Table[i][end + 1] = 0;
                i++;
            }
        }

        private bool ValidateDataIsNull(object Data, string ErrorName, string ErrorMessage)
        {
            if (Data == null || Data.ToString().Length == 0)
            {
                ModelState.AddModelError(ErrorName, ErrorMessage);
                return true;
            }

            return false;
        }

        private void ValidateDataIsNotPositive(int? Data, string ErrorName, string DataName)
        {

            if (Data.Value <= 0)
            {
                ModelState.AddModelError(ErrorName, DataName + " - величина положительная");
            }
        }

        public ActionResult Index()
        {

            IEnumerable<Competition> _Competitions = _DataManager.Competitions.GetAllCompetitions();
            Tour _Tour;
            int i = 0, j, Temp = 0, End;
            int[] QuestionNumber = new int[_Competitions.Count()];
            foreach (Competition c in _Competitions)
            {
                i++;
                j = 0;
                End = 0;
                QuestionNumber[i - 1] = 0;
               
                if (c.IsEnded == true)
                {
                    QuestionNumber[i - 1] = -101;
                }
                else
                {
                    while (true)
                    {
                        j++;
                        _Tour = _DataManager.Tours.GetTour(c.ID, j);
                        if (_Tour == null)
                        {
                            End = 1;
                            break;
                        }
                        Temp = NumberOfCheckedQuestions(_Tour, 3);
                        QuestionNumber[i - 1] += Temp;
                        if (Temp != _Tour.NumberOfQuestions) break;
                    }
                    if (End == 1 && QuestionNumber[i - 1] != 0)
                    {
                        QuestionNumber[i - 1] = -100;
                    }
                    else if (Temp == 0)
                    {
                        QuestionNumber[i - 1] = 0 - j + 1;
                    }
                }
            }


            ViewBag.Message = "Список турниров:";
            ViewBag.Role = _DataManager.Users.GetRoleByLogin(User.Identity.Name);
            ViewData["Competitions"] = _Competitions;
            ViewData.Model = QuestionNumber;

            return View();
        }

        public ActionResult About()
        {
            ViewBag.Message = "It's All About The Game!";
            ViewBag.Role = _DataManager.Users.GetRoleByLogin(User.Identity.Name);
            return View();
        }

        public ActionResult TourTable(int CompetitionID, int TourNumber)
        {
            if (CompetitionID == 0)
            {
                CompetitionID = _DataManager.Competitions.GetCompetitionByUserLogin(User.Identity.Name).ID;
            }

            Tour _Tour = _DataManager.Tours.GetTour(CompetitionID, TourNumber);
            IEnumerable<Team> _Teams = _DataManager.Teams.GetTeams(CompetitionID);
            Answer _Answer;
            short _NumberOfTeams = (short)_Teams.Count();
            short _NumberOfQuestions = (short)_Tour.NumberOfQuestions;
            int i = 0, j, end = NumberOfCheckedQuestions(_Tour, 3);
            short[][] _Table = new short[_Teams.Count()][];

            InitialazeTable(ref _Table, _Teams, end);

            for (i = 1; i <= end; i++)
            {
                j = 0;
                foreach (Team t in _Teams)
                {
                    _Answer = _DataManager.Answers.GetAnswer(t.ID, _Tour.ID, i);
                    if (_Answer != null && _Answer.IsCorrect == true)
                    {
                        _Table[j][i] = 1;
                        _Table[j][end + 1]++;
                    }
                    else
                    {
                        _Table[j][i] = 0;
                    }
                    j++;
                }
             }

            if (end != 0)
            {
                QuickSort(ref _Table, _Teams.Count(), end + 1);

                for (i = 0; i < _Teams.Count(); i++)
                {
                    _Teams.Single(t => t.Number == _Table[i][0]).Number = (short)(i + _Teams.Count() * 2);

                }

                _Teams = _Teams.OrderBy(t => t.Number);
            }

            ViewData.Model = _Table;
            ViewData["CompetitionID"] = CompetitionID;
            ViewData["Competition"] = _DataManager.Competitions.GetName(CompetitionID);
            ViewData["TourNumber"] = _Tour.NumberInCompetition;
            ViewData["Teams"] = _Teams;
            ViewData["NumberOfQuestions"] = end;
            ViewData["NumberOfTours"] = _DataManager.Tours.GetTours(CompetitionID).Count();
            ViewBag.Role = _DataManager.Users.GetRoleByLogin(User.Identity.Name);

            return View();
        }

        public ActionResult SummaryTable(int CompetitionID)
        {
            if (CompetitionID == 0)
            {
                CompetitionID = _DataManager.Competitions.GetCompetitionByUserLogin(User.Identity.Name).ID;
            }

            IEnumerable<Team> _Teams = _DataManager.Teams.GetTeams(CompetitionID);
            Tour _Tour = _DataManager.Tours.GetLastTour(CompetitionID);
            Answer _Answer = new Answer();
            short[][] _Table = new short[_Teams.Count()][];
            int i, k, end=_Tour.NumberInCompetition, EndOfTour, EndOfLastTour = 0;
  
            while (end > 0)
            {
                EndOfLastTour = NumberOfCheckedQuestions(_Tour, 3);
                if (EndOfLastTour != 0)
                {
                    break;
                }
                end--;
                _Tour = _DataManager.Tours.GetTour(CompetitionID, end);
            }

            InitialazeTable(ref _Table, _Teams, end);

            for (i = 1; i<=end; i++)
            {
               _Tour = _DataManager.Tours.GetTour(CompetitionID, i);
               k = 0;

               if (i != end)
               {
                   EndOfTour = _Tour.NumberOfQuestions;
               }
               else
               {
                   EndOfTour = EndOfLastTour;
               }

               foreach (Team t in _Teams)
               {
                   for (int j = 1; j <= EndOfTour; j++)
                   {
                       _Answer = _DataManager.Answers.GetAnswer(t.ID, _Tour.ID, j);
                       if (_Answer == null)
                       {
                           break;
                       }
                       
                       if (_Answer.IsCorrect == true)
                       {
                           _Table[k][i]++;
                       }
                   }
                   _Table[k][end + 1] += _Table[k][i];
                   k++;

               }
            }

            if (end != 0)
            {
                QuickSort(ref _Table, _Teams.Count(), end + 1);

                for (i = 0; i < _Teams.Count(); i++)
                {
                    _Teams.Single(t => t.Number == _Table[i][0]).Number = (short)(i + _Teams.Count() * 2);
                }

                _Teams = _Teams.OrderBy(t => t.Number);
            }

            ViewData.Model = _Table;
            ViewData["CompetitionID"] = CompetitionID;
            ViewData["Competition"] = _DataManager.Competitions.GetName(CompetitionID);
            ViewData["Teams"] = _Teams;
            ViewData["NumberOfTours"] = _DataManager.Tours.GetTours(CompetitionID).Count();
            ViewData["NumberOfUsedTours"] = end;
            ViewBag.Role = _DataManager.Users.GetRoleByLogin(User.Identity.Name);

            return View();
        }

        [HttpGet]
        public ActionResult CreateCompetition()
        {
            string[] Type = {"Очный", "Синхрон"};
            ViewData["Type"] = new SelectList(Type);
            return View();
        }

        [HttpPost]
        public ActionResult CreateCompetition(Competition NewCompetition, string LongDescription, string ShortDescription, int? NumberOfTours, short? NumberOfQuestionsInTour, int? NumberOfSuperusers, string SuperuserName, string Email)
        {
            if (!ValidateDataIsNull(NewCompetition.Name, "CompetitionName", " - Пожалуйста, введите название турнира"))
            {
                if (_DataManager.Competitions.IsCompetitionExist(NewCompetition.Name)) ModelState.AddModelError("CompetitionName", " - Турнир с таким именем уже существует в базе данных. Пожалуйста, выберите другое название или обратитесь к администраторам с просьбой удалить старый турнир");
            }

            if (LongDescription.Length > 990) ModelState.AddModelError("LongDescription", " - Длина описания не может превышать 990 символов");

            if (!ValidateDataIsNull(ShortDescription, "ShortDescription", " - Пожалуйста, введите краткое наименование турнира"))
            {
                if (ShortDescription.Length < 3 || ShortDescription.Length > 7) ModelState.AddModelError("ShortDescription", " - Краткое наименование должно быть в пределах 3-6 символов");
            }

            if (!ValidateDataIsNull(NumberOfTours, "NumberOfTours", " - Пожалуйста, укажите количество туров"))
            {
                ValidateDataIsNotPositive(NumberOfTours, "NumberOfTours", " - Количество туров");
            }

            if (!ValidateDataIsNull(NumberOfQuestionsInTour, "NumberOfQuestionsInTour", " - Пожалуйста, укажите количество вопросов в туре"))
            {
                ValidateDataIsNotPositive(NumberOfQuestionsInTour, "NumberOfQuestionsInTour", " - Количество вопросов в туре");
            }

            if (!ValidateDataIsNull(NumberOfSuperusers, "NumberOfSuperusers", " - Пожалуйста, укажите количество организаторов"))
            {
                ValidateDataIsNotPositive(NumberOfSuperusers, "NumberOfSuperusers", " - Количество организаторов");
            }

            ValidateDataIsNull(SuperuserName, "SuperuserName", " - Пожалуйста, укажите имя и фамилию");

            if (!ValidateDataIsNull(Email, "Email", " - Пожалуйста, укажите контактный e-mail"))
            {
                if (!Email.ToCharArray().Contains('@') || !Email.ToCharArray().Contains('.') || Email.LastIndexOf('@') > Email.LastIndexOf('.') - 3 || Email.IndexOf('@') == 0 || Email.IndexOf('.') > Email.Count() - 3) ModelState.AddModelError("Email", " - Введённый вами e-mail некорректен");
            }

            if (!ModelState.IsValid)
            {
                string[] Type = { "Очный", "Синхрон" };
                ViewData["Type"] = new SelectList(Type);
                return View();
            }


            if (ModelState.IsValid)
            {
                if (LongDescription != null)
                {
                    NewCompetition.Description = LongDescription;
                }
                int CompetitionID = _DataManager.Competitions.CreateCompetition(NewCompetition).ID;
                Random rnd = new Random();
                Password PasswordInstance = new Password();

                for (short i=1;i<=NumberOfTours;i++)
                {
                    _DataManager.Tours.CreateTour(CompetitionID, NumberOfQuestionsInTour.Value, i);
                }

                for (int i=1; i<= NumberOfSuperusers; i++)
                { 
                   _DataManager.Users.CreateUser(ShortDescription + "-s" + i.ToString(),  PasswordInstance.CreatePassword(rnd.Next(8, 11)), "Superuser", CompetitionID);
                }

                MailMessage message = new MailMessage(); // создание нового письма
                message.To.Add("somebody331@gmail.com"); // добавление адреса получателя
                message.From = new MailAddress("system@chgkwebsuite.ru", "chgkwebsuite.ru"); // указание имени и адреса отправителя
                message.Subject = "Создание турнира " + _DataManager.Competitions.GetName(CompetitionID); // указание темы письма 
                message.BodyEncoding = System.Text.Encoding.UTF8; // указание кодировки письма
                message.IsBodyHtml = false; // указание формата письма (true - HTML, false - не HTML)
                message.Body = "Создан новый турнир!\r\nИнформация об организаторе:\r\n\r\nИмя Фамилия: " + SuperuserName + "\r\nE-mail: " + Email; // указание текста (тела) письма

                SmtpClient client = new SmtpClient("smtp.chgkwebsuite.ru", 25); // создание нового подключения к серверу "smtp.domain.tld"
                client.DeliveryMethod = SmtpDeliveryMethod.Network; // определяет метод отправки сообщений
                client.EnableSsl = false; // отключает необходимость использования защищенного соединения с сервером
                client.UseDefaultCredentials = false; // отключение использования реквизитов авторизации "по-умолчанию"
                client.Credentials = new NetworkCredential("postmaster@chgkwebsuite.ru", "po4parka2tin"); // указание нужных реквизитов (имени пользователя и пароля) для авторизации на SMTP-сервере
                client.Send(message); // отправка сообщения

                return RedirectToAction("CreateCompetitionSuccess", new { CompetitionID = CompetitionID});
            }

            return View();
        }

        public ActionResult CreateCompetitionSuccess(int CompetitionID)
        {
            ViewData["Superusers"] = _DataManager.Users.GetUsers(CompetitionID, "Superuser");
            ViewData["CompetitionName"] = _DataManager.Competitions.GetName(CompetitionID);
            
            return View();
        }

        
    }
}
